最近工作上需要写一套跨服务器分隔数据和转移数据的脚本。经过实践,发现单纯执行在本地执行命令来操控远程服务器的数据不现实。所以需要把脚本放在远程服务器,然后本地让服务器自己去执行脚本。此外,需要使用 expect 工具来自动输入远程服务器登录密码。
先提一些 expect 的用法,即可以写成 expect 脚本形式 (即脚本以 #!/usr/bin/expect 开头),也可以写成 expect -c ‘<several_cmd>’ 的单条命令形式。后者的示例形式:
1
| expect -c 'spawn scp root@example:~/xx.txt .; expect "password:"; send "abc1234\\r"; interact;'
|
上面例子中,spawn 后面表示需要执行的命令 (此处是一个 scp 命令,需要输入密码,这就是为什么要 expect 的原因),expect 后面是表示标准输出出现 “password:” 字样时,就自动输入 send 后面的东西,也就是密码。最后一个 interact 表示接下来允许用户自己交互。
本来直接使用 shell 脚本就可以的。不过我这设计到数据的切割,所以就使用了 Python,然后需要用到 shell 命令时,是由 Python 脚本再调用 shell 命令的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import os
def call_remote_cmd(host, password, cmd): """ 让远程服务器自己执行命令 :param host: 远程服务器用户名加域名,格式示例:root@example.com :param cmd: 要让远程服务器执行的命令 :return: 一些结果,其中可能有一些提示性文本 """ final_cmd = '/usr/bin/expect -c \'spawn ssh %s %s; expect "*Password:"; send "%s\\r"; interact;\'' % (host, cmd, password) res = os.popen(final_cmd).read() print(res) return res
args = {'a': 1, 'b': [1, 2, 3]}
args = str(args) args = args.replace('\'', '\\\"') args = args.replace(' ', '\\ ') args = args.replace(',', '\\,') args = args.replace('[', '\\[') args = args.replace(']', '\\]') args = args.replace('{', '\\{') args = args.replace('}', '\\}') args = args.replace(';', '\\;') args = args.replace('"', '\\"')
cmd = '/usr/local/bin/python3 x.py \\"%s\\"' % args call_remote_cmd('root@example.com', 'password', cmd)
|
上面是我因工作需要而写出来的让远程服务器执行它的 Python 脚本的本地 Python 脚本代码。使用的时候就简单了。服务器上面放一个被调用的 Python 脚本。然后执行上面代码,就可以了。
想必直接写 shell 脚本的话,可能会更简洁些。等啥时候有空了试试看。